import yaml
from selenium.webdriver.chrome import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.remote.webelement import WebElement
import os
import time

class BasePage:
    def __init__(self, driver):
        """
        初始化基类页面对象。

        :param driver: WebDriver 实例
        :param base_url: 基础 URL
        """
        self.driver = driver

    def find_element(self, locator, timeout=10):
        """
        查找单个元素。

        :param locator: 元素定位器 (By.ID, By.NAME, By.XPATH 等)
        :param timeout: 显示等待超时时间
        :return: WebDriverElement
        """
        return WebDriverWait(self.driver, timeout).until(
            EC.presence_of_element_located(locator)
        )

    def find_elements(self, locator, timeout=10):
        """
        查找多个元素。

        :param locator: 元素定位器 (By.ID, By.NAME, By.XPATH 等)
        :param timeout: 显示等待超时时间
        :return: list of WebDriverElements
        """
        return WebDriverWait(self.driver, timeout).until(
            EC.presence_of_all_elements_located(locator)
        )

    def take_screenshot(self, filename):
        """
        截图并保存。

        :param filename: 截图文件名
        """
        screenshot_dir = 'screenshots'
        if not os.path.exists(screenshot_dir):
            os.makedirs(screenshot_dir)
        filepath = os.path.join(screenshot_dir, filename)
        self.driver.save_screenshot(filepath)

    def scroll_to_element(self, element, offset=0):
        """
        使用 JavaScript 滚动到指定元素。

        :param element: WebDriverElement
        :param offset: 滚动偏移量
        """
        self.driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'nearest'}); arguments[0].scrollBy(0, arguments[1]);", element, offset)

    def right_click(self, element):
        """
        使用 ActionChains 进行右键点击。

        :param element: WebDriverElement
        """
        actions = ActionChains(self.driver)
        actions.context_click(element).perform()

    def switch_to_frame(self, frame_reference):
        """
        切换到指定的 iframe 框架。

        :param frame_reference: iframe 的定位器 (By.ID, By.NAME, By.XPATH 等) 或者 WebElement
        """
        if isinstance(frame_reference, WebElement):
            self.driver.switch_to.frame(frame_reference)
        else:
            self.driver.switch_to.frame(frame_reference)

    def enter_debug_mode(self):
        """
        进入调试模式，允许在浏览器中使用开发者工具。
        """
        capabilities = DesiredCapabilities.CHROME.copy()
        capabilities['goog:loggingPrefs'] = {'performance': 'ALL'}
        self.driver = webdriver.Chrome(desired_capabilities=capabilities)
        # 注意：这里需要重新实例化 WebDriver，因为原来的 WebDriver 实例可能不支持调试模式

    def upload_file(self, locator, file_path):
        """
        上传文件到指定的输入框。

        :param locator: 文件输入框的定位器 (By.ID, By.NAME, By.XPATH 等)
        :param file_path: 要上传的文件路径
        """
        element = self.find_element(locator)
        element.send_keys(file_path)

    def open(self, url):
        """
        打开指定的 URL。

        :param url: 要打开的 URL
        """
        full_url = f"{self.base_url}/{url}" if self.base_url else url
        self.driver.get(full_url)

    def is_visible(self, locator, timeout=10):
        """
        判断元素是否可见。

        :param locator: 元素定位器 (By.ID, By.NAME, By.XPATH 等)
        :param timeout: 显示等待超时时间
        :return: bool
        """
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.visibility_of_element_located(locator)
            )
            return element.is_displayed()
        except:
            return False

    def click(self, locator, timeout=10):
        """
        点击元素。

        :param locator: 元素定位器 (By.ID, By.NAME, By.XPATH 等)
        :param timeout: 显示等待超时时间
        """
        element = self.find_element(locator, timeout)
        element.click()

    def send_keys(self, locator, value, timeout=10):
        """
        向元素发送文本。

        :param locator: 元素定位器 (By.ID, By.NAME, By.XPATH 等)
        :param value: 要发送的文本值
        :param timeout: 显示等待超时时间
        """
        element = self.find_element(locator, timeout)
        element.clear()
        element.send_keys(value)

    def take_screenshot(self, filename):
        """
        截图并保存。

        :param filename: 截图文件名
        """
        screenshot_dir = 'screenshots'
        if not os.path.exists(screenshot_dir):
            os.makedirs(screenshot_dir)
        filepath = os.path.join(screenshot_dir, filename)
        self.driver.save_screenshot(filepath)

    # 其他方法...

    # 新增的截图方法
    def take_screenshot_on_failure(self, test_name):
        """
        当测试失败时自动截图。

        :param test_name: 测试函数的名称
        """
        timestamp = time.strftime("%Y%m%d%H%M%S", time.localtime())
        filename = f"{test_name}_{timestamp}.png"
        self.take_screenshot(filename)

class FileIO:
    @staticmethod
    def read_yaml(file_path):
        with open(file_path, 'r', encoding='utf-8') as file:
            data = yaml.safe_load(file)
            if isinstance(data, dict):
                return [data]
            elif isinstance(data, list):
                return data
            else:
                raise ValueError("YAML 文件内容不是有效的字典或列表")
    @staticmethod
    def write_yaml(data, file_path):
        """Writes data to a YAML file."""
        with open(file_path, 'w', encoding='utf-8') as file:
            yaml.dump(data, file, default_flow_style=False)